<?php
/*
 * For explanation and usage, see:
 * http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class/
 */
class JG_Cache
{

    function __construct ($dir)
    {
        $this->dir = $dir;
        if (! file_exists($this->dir)) {
            if (! mkdir($this->dir, 0777, true)) {
                echo 'Failed to create folders...';
            }
        }
    }

    public function cachedFileName ($key)
    {
        return sprintf("%s/%s", $this->dir, sha1($key));
    }

    /**
     * 是否有可用的缓存数据
     * 
     * @param unknown_type $key            
     * @param unknown_type $expiration            
     */
    public function available ($key, $minFileSize, $expiration = 3600)
    {
        $kDebug = false;
        if (! is_dir($this->dir) or ! is_writable($this->dir)) {
            return FALSE;
        }
        
        $cache_path = $this->cachedFileName($key);
        if ($kDebug) {
            echo '$cache_path:' . $cache_path . "</br>";
        }
        if (! @file_exists($cache_path)) {
            if ($kDebug) {
                echo "$cache_path: " . "not found" . "</br>";
            }
            return FALSE;
        }
        
        if (filemtime($cache_path) < (time() - $expiration)) {
            if ($kDebug) {
                echo '$cache_path:' . "timed out" . "</br>";
            }
            $this->clear($key);
            return FALSE;
        }
        if (filesize($cache_path) < $minFileSize) {
            return FALSE;
        }
        if ($kDebug) {
            echo '$cache_path:' . "matched" . "</br>";
        }
        return TRUE;
    }

    public function get ($key, $normal = TRUE, $expiration = 3600)
    {
        if (! $this->available($key, $expiration)) {
            return FALSE;
        }
        $cache_path = $this->cachedFileName($key);
        if (! $fp = @fopen($cache_path, 'rb')) {
            return FALSE;
        }
        
        flock($fp, LOCK_SH);
        
        $cache = '';
        
        if (filesize($cache_path) > 0) {
            $cache = fread($fp, filesize($cache_path));
            if (! $normal)
                $cache = unserialize($cache);
        } else {
            $cache = NULL;
        }
        
        flock($fp, LOCK_UN);
        fclose($fp);
        
        return $cache;
    }

    /**
     * 返回加密后的文件路径
     * 
     * @param unknown_type $key            
     * @param unknown_type $data            
     * @return string
     */
    public function set ($key, $data, $normal = TRUE)
    {
        if (! is_dir($this->dir) or ! is_writable($this->dir)) {
            return "";
        }
        
        $cache_path = $this->cachedFileName($key);
        
        if (! $fp = fopen($cache_path, 'wb')) {
            return "";
        }
        
        if (flock($fp, LOCK_EX)) {
            if ($normal) {
                fwrite($fp, $data);
            } else {
                fwrite($fp, serialize($data));
            }
            flock($fp, LOCK_UN);
        } else {
            return "";
        }
        fclose($fp);
        @chmod($cache_path, 0777);
        return $cache_path;
    }

    public function clear ($key)
    {
        $cache_path = $this->cachedFileName($key);
        
        if (file_exists($cache_path)) {
            unlink($cache_path);
            return TRUE;
        }
        
        return FALSE;
    }
}